/*
 * Copyright Aristool AG Switzerland
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License. 
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0 
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */

package org.opprua.dss.application;

import java.util.Map;
import java.util.Stack;

import org.opprua.dss.data.Result;
import org.opprua.tidy.util.XReader;
import org.w3c.dom.Element;

/**
 * TODO: add Java doc
 * 
 * Prepared for first commit: 23.02.2007
 * 
 * @author Lin Li
 */
public class DEntry extends XReader {

  private DCall[] calls;
  private Class<? extends Object> type;

  @Override
  public void read(Element e) {
    calls = collect(e, "call", DCall.class);
  }

  public void registerCalls(DApplication app) {
    for (int i = 0; i < calls.length; i++) {
      calls[i].setParamType(getTypeName());

      calls[i].setReturnType(null);
      if (RUtil.has(calls[i].getRelay())) {
        calls[i].setReturnType(app.getEntry(calls[i].getRelay()).getTypeName());
      }

      calls[i].register(app);
    }
  }

  public String getName() {
    return getAttribute("name");
  }

  public String getTypeName() {
    String t = getAttribute("type");
    if (t == null || t.equals("null")) {
      t = "org.opprua.tidy.util.Scriptable";
      setAttribute("type", t);
    }
    return t;
  }

  public Class<? extends Object> getType() {
    if (type == null) {
      if (RUtil.isType(getTypeName())) {
        type = RUtil.getScriptable(getTypeName());
      } else {
        type = Object.class;
      }
    }
    if (type.equals(Object.class)) return null;
    return type;
  }

  public DCall[] getCalls() {
    return calls;
  }

  public Map<String, String> execute(Object param, DApplication app, Stack<String> called) {
    called.push(this.getName());
    for (int i = 0; i < calls.length; i++) {
      Result<?> s = calls[i].call(param);
      if (s.getType() == Result.TYPE.FAILURE) { return s.getReason(); }
      String re = calls[i].getRelay();
      if (RUtil.has(re) && s.getType() == Result.TYPE.SUCCESS && !called.contains(re)) {
        Map<String, String> res = app.getEntry(re).execute(s.getData(), app, called);
        if (res != null) { return res; }
      }
    }
    called.pop();
    return null;
  }
}
